Skip to content

Support hot reload over websocket #2616

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

jyameo
Copy link
Contributor

@jyameo jyameo commented May 6, 2025

  • Added WebSocket-based hot reload support: reloadSources in ChromeProxyService and DevHandler can now handle hot reload requests and responses over WebSockets (protected by bool flag useWebSocket).
  • Refactored the injected client to use a reusable function for handling hot reload requests and responses over WebSockets.

Related to #2605

@jyameo jyameo requested review from srujzs and biggs0125 May 6, 2025 15:45
Copy link
Contributor

@srujzs srujzs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Jessy! This generally looks good % my comment about requests coming in too quick.


/// Pending hot reload requests waiting for a response from the client.
/// Keyed by the request ID.
final _pendingHotReloads = <String, Completer<HotReloadResponse>>{};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way the hot reload works in the client is it looks at the hotReloadSourcesUri which contains all the changed files and their libraries and then does an XHR. If whatever app that calls DWDS sends requests too quickly, it may be a possible that a hot reload request reads a version of the file that is no longer the correct version.

For example, the app sends a request and then sets the data in that URI. The app sends a second request with new data in that URI before the first request finishes. Then the first request is reading the new data instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. This makes sense. If I add a request/response mechanism for fetchLibrariesForHotReload, similar to how I handle HotReloadRequest with a Completer, would that help resolve the possible race condition you described? Essentially by sending a FetchLibrariesForHotReloadRequest and waiting for its response (using a Completer), we can ensure that the client fetches the correct set of changed libraries before proceeding to the hot reload step. What do you think about this approach?

Copy link
Contributor

@srujzs srujzs May 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we want to have the completer wait for both fetchLibrariesForHotReload and hotReload. The former may return the right paths now, but those paths may be replaced with new compiled files before hotReload gets to execute if we don't wait for hotReload as well.

But I believe that should work. This more or less "blocks" the request queue until the previous request is fully finished.

@@ -366,6 +370,49 @@ Future<bool> _authenticateUser(String authUrl) async {
return responseText.contains('Dart Debug Authentication Success!');
}

// handle hot reload request/response logic.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Remove this comment or add more detail. Function name gives this same info.

final requestId = event.id;
try {
// Execute the hot reload.
await manager.fetchLibrariesForHotReload(hotReloadSourcesPath);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on the comments above it seems like these both need to happen before we 'ack' the hot reload request. I'm not clear on a couple things:

  1. Why do these need to be 2 separate functions if we need to make sure they're called together anyway?
  2. Once the future from fetchLibrariesForHotReload completes the files are loaded into the page and we have an ID associated with the request so we can avoid mixing up files. Why do we need to wait for the client to finish applying the hot reload patch (i.e. calling hotReload) to 'ack' the server and unblock it to process further requests?

cc @srujzs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants